package com.gorge4j.user;

import java.sql.Connection; // 表示连接到某个数据库的连接类
import java.sql.DriverManager; // 用来获取数据库连接类
import java.sql.PreparedStatement; // 用来编译和执行SQL语句的类，支持占位符的方式，比Statement功能更强大，性能更好更安全
import java.sql.ResultSet; // 封装查询结果集的类
import java.sql.SQLException; // SQL异常类
import java.sql.Statement; // 用来编译和执行SQL语句的类
import java.util.ArrayList; // JDK常用ArrayList类
import java.util.List; // JDK常用List类
import java.util.logging.Logger;
import com.gorge4j.user.constant.ResponseConstant;
import com.gorge4j.user.constant.SqlConstant; // 数据库连接静态常量类
import com.gorge4j.user.constant.UserTypeConstant; // 用户类型静态常量类
import com.gorge4j.user.dto.DeleteDTO; // 用户删除数据传输对象
import com.gorge4j.user.dto.LoginDTO; // 用户登录数据传输对象
import com.gorge4j.user.dto.ModifyDTO; // 密码修改数据传输对象
import com.gorge4j.user.dto.RegisterDTO; // 用户注册数据传输对象
import com.gorge4j.user.util.Base64Util;
import com.gorge4j.user.vo.ResponseVO; // 统一返回对象
import com.gorge4j.user.vo.UserVO; // 用户信息值对象
import com.gorge4j.user.vo.ViewVO; // 用户列表展示值对象

/**
 * @Title: BusinessOperationBean.java
 * @Description: 用户项目业务处理类
 * @Copyright: © 2019 ***
 * @Company: ***有限公司
 *
 * @author gorge.guo
 * @date 2019-04-07 20:46:52
 * @version v1.0
 */

public class BusinessOperationBean {

    private static Logger log = Logger.getLogger("BusinessOperationBean");

    /** 数据库连接对象 */
    private Connection conn = null;
    /** 登录操作数据传输对象 */
    private LoginDTO loginDTO;
    /** 注册操作数据传输对象 */
    private RegisterDTO registerDTO;
    /** 密码修改操作数据对象 */
    private ModifyDTO modifyDTO;
    /** 删除操作数据对象 */
    private DeleteDTO deleteDTO;

    /** 获得数据库连接（在JSP页面里类被实例化的时候，执行下边的类的构造函数） */
    public BusinessOperationBean() {
        // try/catch逻辑用来捕捉可能出现的异常
        try {
            // 使用反射的特性加载数据库驱动
            Class.forName(SqlConstant.DRIVER);
            // 连接数据库
            conn = DriverManager.getConnection(SqlConstant.DB_URL, SqlConstant.DB_USER,
                    Base64Util.base64Decrypt(SqlConstant.DB_PASS));
        } catch (Exception e) {
            // 如果执行过程中出现异常则打印异常信息
            log.severe(e.getMessage());
        }
    }

    /**
     * 用户注册
     * 
     * @return
     */
    public ResponseVO register() {
        // 定义返回的对象
        ResponseVO responseVO = new ResponseVO();
        // 创建一个可以设置占位符参数的可编译和执行SQL的对象
        PreparedStatement stmt = null;
        // try/catch逻辑用来捕捉可能出现的异常
        try {
            if (checkUserDuplicate(registerDTO.getName(), UserTypeConstant.ORDINARY)) {
                responseVO.setCode(ResponseConstant.FAIL);
                responseVO.setMessage("用户名重复，请重新注册！");
                // 返回组装的提示信息对象给前端页面
                return responseVO;
            }
            // 创建一个可以设置占位符参数的可编译和执行SQL的对象
            String strSql2 =
                    "INSERT INTO user_manage_demo (name, password, type, gmt_create, gmt_modified, is_delete) VALUES (?, ?, ?, ?, ?, ?)";
            stmt = conn.prepareStatement(strSql2);
            // 下面5行语句设置占位符里的各个参数（逐一替换前面一句里的？占位符），注意参数类型
            stmt.setString(1, registerDTO.getName());
            stmt.setString(2, registerDTO.getPassword());
            stmt.setString(3, UserTypeConstant.ORDINARY);
            stmt.setTimestamp(4, new java.sql.Timestamp(new java.util.Date().getTime()));
            stmt.setTimestamp(5, new java.sql.Timestamp(new java.util.Date().getTime()));
            stmt.setBoolean(6, Boolean.FALSE);
            // 执行编译后的SQL语句
            stmt.execute();
            // 组装返回的结果对象
            responseVO.setCode(ResponseConstant.SUCCESS);
            responseVO.setMessage("恭喜您，注册成功！请登录");
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(null, stmt, conn);
        } catch (SQLException se) {
            // 捕捉JDBC异常
            log.severe(se.getMessage());
        } catch (Exception e) {
            // 如果执行过程中出现异常则打印异常信息
            log.severe(e.getMessage());
        } finally { // 无论何种情况，都会执行下边的语句（finally的作用），关闭数据库连接
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(null, stmt, conn);
        }
        // 返回组装好的结果
        return responseVO;
    }

    /**
     * 用户登录
     * 
     * @return
     */
    public UserVO login() {
        // 定义返回的结果集对象，这种定义方式是对象形式的集合
        UserVO userVO = null;
        // 创建一个可编译和执行SQL的对象
        Statement stmt = null;
        // 根据执行SQL返回的结果封装结果集
        ResultSet rs = null;
        // try/catch逻辑用来捕捉可能出现的异常
        try {
            stmt = conn.createStatement();
            rs = stmt.executeQuery("SELECT name, type FROM user_manage_demo WHERE name = '" + loginDTO.getName()
                    + "' AND password = '" + loginDTO.getPassword() + "' AND type = '" + loginDTO.getType()
                    + "' AND is_delete = false");
            // 如果数据库存在记录，则将记录添加到返回的结果集对象中
            if (rs.next()) {
                userVO = new UserVO();
                // 下边给对象附值
                userVO.setName(rs.getString("name"));
                userVO.setType(rs.getString("type"));
            }
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(rs, stmt, conn);
        } catch (SQLException se) {
            // 捕捉JDBC异常
            log.severe(se.getMessage());
        } catch (Exception e) {
            // 如果执行过程中出现异常则打印异常信息
            log.severe(e.getMessage());
        } finally { // 无论何种情况，都会执行下边的语句（finally的作用），关闭数据库连接
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(rs, stmt, conn);
        }
        // 返回组装好的结果集
        return userVO;
    }

    /**
     * 添加用户
     * 
     * @return
     */
    public ResponseVO addUser() {
        // 定义返回的对象
        ResponseVO responseVO = new ResponseVO();
        // 创建一个可以设置占位符参数的可编译和执行SQL的对象
        PreparedStatement stmt = null;
        // try/catch逻辑用来捕捉可能出现的异常
        try {
            if (checkUserDuplicate(registerDTO.getName(), UserTypeConstant.ORDINARY)) {
                responseVO.setCode(ResponseConstant.FAIL);
                responseVO.setMessage("用户名重复，请重新添加！");
                // 返回组装的提示信息对象给前端页面
                return responseVO;
            }
            // 创建一个可以设置占位符参数的可编译和执行SQL的对象
            String strSql2 =
                    "INSERT INTO user_manage_demo (name, password, type, gmt_create, gmt_modified, is_delete) VALUES (?, ?, ?, ?, ?, ?)";
            stmt = conn.prepareStatement(strSql2);
            // 下面5行语句设置占位符里的各个参数（逐一替换前面一句里的？占位符），注意参数类型
            stmt.setString(1, registerDTO.getName());
            stmt.setString(2, registerDTO.getPassword());
            stmt.setString(3, UserTypeConstant.ORDINARY);
            stmt.setTimestamp(4, new java.sql.Timestamp(new java.util.Date().getTime()));
            stmt.setTimestamp(5, new java.sql.Timestamp(new java.util.Date().getTime()));
            stmt.setBoolean(6, Boolean.FALSE);
            stmt.execute(); // 执行编译后的SQL语句
            // 组装返回的结果对象
            responseVO.setCode(ResponseConstant.SUCCESS);
            responseVO.setMessage("添加成功！");
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(null, stmt, conn);
        } catch (SQLException se) {
            // 捕捉JDBC异常
            log.severe(se.getMessage());
        } catch (Exception e) {
            // 捕捉Class.forName异常
            log.severe(e.getMessage());
        } finally { // 无论何种情况，都会执行下边的语句（finally的作用），关闭数据库连接
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(null, stmt, conn);
        }
        // 返回组装好的结果
        return responseVO;
    }

    /**
     * 查看用户列表
     * 
     * @return
     */
    public List<ViewVO> view() {
        // 定义返回的结果集对象，这种定义方式是对象形式的集合
        List<ViewVO> lstViewVOs = new ArrayList<>();
        // 定义一个可编译和执行SQL的对象
        Statement stmt = null;
        // 定义一个SQL结果集集合
        ResultSet rs = null;
        // try/catch逻辑用来捕捉可能出现的异常
        try {
            // 创建一个可编译和执行SQL的对象
            stmt = conn.createStatement();
            // 根据执行SQL返回的结果封装结果集
            rs = stmt.executeQuery("SELECT id, name, type, gmt_create FROM user_manage_demo WHERE type = '"
                    + UserTypeConstant.ORDINARY + "' AND is_delete = false");
            // 如果数据库存在记录，则将记录添加到返回的结果集对象中
            while (rs.next()) {
                // 创建一个新对象来存储查询出的一条条记录
                ViewVO viewVO = new ViewVO();
                // 下边给对象附值
                viewVO.setId(rs.getInt("id"));
                viewVO.setName(rs.getString("name"));
                viewVO.setType(UserTypeConstant.typeToDesc(rs.getString("type")));
                viewVO.setGmtCreate(rs.getDate("gmt_create"));
                // 将对象放入结果集中
                lstViewVOs.add(viewVO);
            }
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(rs, stmt, conn);
        } catch (SQLException se) {
            // 捕捉JDBC异常
            log.severe(se.getMessage());
        } catch (Exception e) {
            // 如果执行过程中出现异常则打印异常信息
            log.severe(e.getMessage());
        } finally { // 无论何种情况，都会执行下边的语句（finally的作用），关闭数据库连接
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(rs, stmt, conn);
        }
        // 返回组装好的结果集
        return lstViewVOs;
    }

    /**
     * 密码修改
     * 
     * @return
     */
    public ResponseVO modify() {
        // 定义返回的对象
        ResponseVO responseVO = new ResponseVO();
        // 创建一个可以设置占位符参数的可编译和执行SQL的对象
        PreparedStatement stmt = null;
        // try/catch逻辑用来捕捉可能出现的异常
        try {
            // 判断新密码和确认密码是否一致
            if (modifyDTO.getNewPassword() != null && modifyDTO.getConfirmNewPassword() != null
                    && !modifyDTO.getNewPassword().equals(modifyDTO.getConfirmNewPassword())) {
                responseVO.setCode(ResponseConstant.FAIL);
                responseVO.setMessage("新密码和确认新密码不一致，请检查");
                // 返回组装的提示信息对象给前端页面
                return responseVO;
            }
            stmt = conn.prepareStatement(
                    "UPDATE user_manage_demo SET password = ?, gmt_modified = ? WHERE name = ? AND type = ?");
            // 下面5行语句设置占位符里的各个参数（逐一替换前面一句里的？占位符），注意参数类型
            stmt.setString(1, modifyDTO.getNewPassword());
            stmt.setTimestamp(2, new java.sql.Timestamp(new java.util.Date().getTime()));
            stmt.setString(3, modifyDTO.getName());
            stmt.setString(4, modifyDTO.getType());
            // 执行编译后的SQL语句
            stmt.execute();
            // 组装返回的结果对象
            responseVO.setCode(ResponseConstant.SUCCESS);
            responseVO.setMessage("密码修改成功！");
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(null, stmt, conn);
        } catch (SQLException se) {
            // 捕捉JDBC异常
            log.severe(se.getMessage());
        } catch (Exception e) {
            // 如果执行过程中出现异常则打印异常信息
            log.severe(e.getMessage());
        } finally { // 无论何种情况，都会执行下边的语句（finally的作用），关闭数据库连接
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(null, stmt, conn);
        }
        // 返回组装好的结果
        return responseVO;
    }

    /**
     * 逻辑删除指定用户
     * 
     * @return
     */
    public ResponseVO delete() {
        // 定义返回的结果对象
        ResponseVO responseVO = new ResponseVO();
        // 创建一个可编译和执行SQL的对象
        Statement stmt = null;
        // try/catch逻辑用来捕捉可能出现的异常
        try {
            stmt = conn.createStatement();
            // 注意：execute函数返回值true和false并不是代表是否执行成功的意思，所以这里没有用。具体返回值的含义可以看下Statement的executeUpdate方法的返回结果的含义
            int iResult =
                    stmt.executeUpdate("UPDATE user_manage_demo SET is_delete = true WHERE id = " + deleteDTO.getId());
            if (iResult == 1) {
                responseVO.setCode(ResponseConstant.SUCCESS);
                responseVO.setMessage("删除成功！");
            }
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(null, stmt, conn);
        } catch (SQLException se) {
            // 捕捉JDBC异常
            log.severe(se.getMessage());
        } catch (Exception e) {
            // 如果执行过程中出现异常则打印异常信息
            log.severe(e.getMessage());
        } finally {
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(null, stmt, conn);
        }
        // 返回组装好的结果
        return responseVO;

    }

    /**
     * 检查用户是否重复
     * 
     * @param name 名字
     * @param type 类型
     * @return
     */
    private boolean checkUserDuplicate(String name, String type) {
        // 创建一个可编译和执行SQL的对象
        Statement stmt = null;
        ResultSet rs = null;
        boolean isDuplicate = false;
        try {
            stmt = conn.createStatement();
            // 根据执行SQL返回的结果封装结果集
            String strSql1 = "SELECT name, type FROM user_manage_demo WHERE name = '" + name + "' AND type = " + type;
            rs = stmt.executeQuery(strSql1);
            // 如果数据库存在记录，说明当前注册的用户名重复
            while (rs.next()) {
                isDuplicate = true;
            }
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(null, stmt, null);
        } catch (SQLException se) {
            // 捕捉JDBC异常
            log.severe(se.getMessage());
        } catch (Exception e) {
            // 如果执行过程中出现异常则打印异常信息
            log.severe(e.getMessage());
        } finally { // 无论何种情况，都会执行下边的语句（finally的作用），关闭数据库连接
            // 关闭数据库相关连接对象
            closeResultSetAndStatementAndConnection(rs, stmt, null);
        }
        return isDuplicate;
    }

    /**
     * 关闭数据库相关连接
     * 
     * @param rs 结果集
     * @param stmt 连接表对象
     * @param conn 数据库连接
     */
    private void closeResultSetAndStatementAndConnection(ResultSet rs, Statement stmt, Connection conn) {
        // 关闭结果集
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException se) {
            log.severe(se.getMessage());
        }
        // 关闭连接表对象
        try {
            if (stmt != null) {
                stmt.close();
            }
        } catch (SQLException se) {
            log.severe(se.getMessage());
        }
        // 关闭数据库连接
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException se) {
            log.severe(se.getMessage());
        }
    }

    public void setLoginDTO(LoginDTO loginDTO) {
        this.loginDTO = loginDTO;
    }

    public void setRegisterDTO(RegisterDTO registerDTO) {
        this.registerDTO = registerDTO;
    }

    public void setPasswordDTO(ModifyDTO passwordDTO) {
        this.modifyDTO = passwordDTO;
    }

    public ModifyDTO getPasswordDTO() {
        return modifyDTO;
    }

    public DeleteDTO getDeleteDTO() {
        return deleteDTO;
    }

    public void setDeleteDTO(DeleteDTO deleteDTO) {
        this.deleteDTO = deleteDTO;
    }

}
